import json
import time
import logging
import datetime
import pandas as pd

import QUANTAXIS as QA
from QAStrategy.QAStrategy.qastockbase import QAStrategyStockBase
from QAPUBSUB.QAPUBSUB.producer import publisher, publisher_routing
from QAPUBSUB.QAPUBSUB.consumer import subscriber
from QATrader.QATRADER.trader import QA_TRADER
from QIFIAccount.QIFIAccount.QARealtimeStockSim import QIFI_StockSIM_Account
from QUANTAXIS_RealtimeCollector.QARealtimeCollector.collectors.stock_min_bar_collector import QARTCStockMinBar
from QUANTAXIS_RealtimeCollector.QARealtimeCollector.datahandler.stock_resampler import QARTCStockBarResampler


def MACD_JCSC(dataframe, SHORT=12, LONG=26, M=9):
    """
    1.DIF向上突破DEA，买入信号参考。
    2.DIF向下跌破DEA，卖出信号参考。
    """
    CLOSE = dataframe.close
    DIFF = QA.EMA(CLOSE, SHORT) - QA.EMA(CLOSE, LONG)
    DEA = QA.EMA(DIFF, M)
    MACD = 2*(DIFF-DEA)

    CROSS_JC = QA.CROSS(DIFF, DEA)
    CROSS_SC = QA.CROSS(DEA, DIFF)
    return pd.DataFrame({'DIFF': DIFF, 'DEA': DEA, 'MACD': MACD, 'CROSS_JC': CROSS_JC, 'CROSS_SC': CROSS_SC, 'CLOSE': CLOSE})

class SendPrice(QAStrategyStockBase):
    def on_bar(self, bar):
        # print(bar)
        res = self.market_data.groupby(level=1, sort=False).apply(MACD_JCSC)
        # print(res)
        end = res.loc[res.index.levels[0][-1]]
        # for item in bar.index.levels[1]:
        for code in end.index:
            daily_ind = res.xs(code, level=1)
            # print(daily_ind)
            cur_price = daily_ind.CLOSE.iloc[-1]
            print('%s : %.2f' % (code, cur_price))
            if daily_ind.CROSS_JC.iloc[-1] > 0:
                print(daily_ind.iloc[-1])
                text = 'UP CROSS %s : %s current price is %.2f' % (str(datetime.datetime.now()),
                                                      code, cur_price)
                print(text)
                QA.QAUtil.QA_util_sendDD(msg=text)
            if daily_ind.CROSS_SC.iloc[-1] > 0:
                print(daily_ind.iloc[-1])
                text = 'DN CROSS %s : %s current price is %.2f' % (str(datetime.datetime.now()),
                                                      code, cur_price)
                print(text)
                QA.QAUtil.QA_util_sendDD(msg=text)

    def macd(self,):
        return QA.QA_indicator_MACD(self.market_data)


class SendOrder(QAStrategyStockBase):
    def on_bar(self, bar):
        # print(bar)
        res = self.macd()
        ex = QA.CROSS(res['MACD'], 0)
        ec = QA.CROSS(0, res['MACD'])
        end = res.loc[res.index.levels[0][-1]]
        # for item in bar.index.levels[1]:
        for item in end.index:
            text = '%s : %s current price is %.2f' % (str(datetime.datetime.now()),
                                                      item,
                                                      bar.loc[(bar.index.levels[0][-1], item), 'close'])
            print(text)
            self.send_order('BUY', 'OPEN', price=bar.loc[(res.index.levels[0][-1], item), 'close'], volume=100, code=item)

    def macd(self,):
        return QA.QA_indicator_MACD(self.market_data)

class MACD(QAStrategyStockBase):
    def on_bar(self, bar):
        print(bar)
        res = self.macd()
        ex = QA.CROSS(res['MACD'], 0)
        ec = QA.CROSS(0, res['MACD'])
        # print(ex.loc[res.index.levels[0][-1]])
        # print(res.loc[(res.index.levels[0][-1], slice(None)), :])
        end = res.loc[res.index.levels[0][-1]]
        # print(end)
        for item in end.index:
            # print(item)
            # print(ex.loc[res.index.levels[0][-1]][item])
            # print(end.loc[item].DIF)
            # print(bar.loc[(res.index.levels[0][-1], item), 'close'])
            if end.loc[item].DIF > end.loc[item].DEA and ex.loc[res.index.levels[0][-1]][item] > 0:
                print('LONG')
                self.send_order('BUY', 'OPEN', price=bar.loc[(res.index.levels[0][-1], item), 'close'], volume=100,
                                code=item)
            elif end.loc[item].DEA > end.loc[item].DIF and ec.loc[res.index.levels[0][-1]][item] > 0:
                print('SHORT')
                self.send_order('SELL', 'OPEN', price=bar.loc[(res.index.levels[0][-1], item), 'close'], volume=100,
                                code=item)
        # if res.DIF[-1] > res.DEA[-1]:
        #     print('LONG')
        #     if self.positions.volume_long == 0:
        #         self.send_order('BUY', 'OPEN', price=bar['close'], volume=1)
            # if self.positions.volume_short > 0:
            #     self.send_order('BUY', 'CLOSE', price=bar['close'], volume=1)
        # else:
        #     print('SHORT')
        #     if self.positions.volume_short == 0:
        #         self.send_order('SELL', 'OPEN', price=bar['close'], volume=1)
            # if self.positions.volume_long > 0:
            #     self.send_order('SELL', 'CLOSE', price=bar['close'], volume=1)

    def macd(self,):
        return QA.QA_indicator_MACD(self.market_data)

    def risk_check(self):
        pass
        # pprint.pprint(self.qifiacc.message)

def main():
    # account
    acc = QIFI_StockSIM_Account('sim_test1', '123456', init_cash=1e5)
    acc.initial()
    acc.log(acc.message)

    # code pool
    # codes = ['000002', '000100']
    codes = ['002664']

    # subscribe codes
    print('start subscribe codes')
    for code in codes:
        publisher_routing(exchange='QARealtime_Market', routing_key='stock').pub(
            json.dumps({
                'topic': 'subscribe',
                'code': code
            }), routing_key='stock'
        )
        print('Subscribe code %s' % code)
        time.sleep(1)

    # # trader
    # trader = QA_TRADER(account_cookie=acc.message['account_cookie'], password=acc.message['password'],
    #                    wsuri='ws://10.15.0.107:8050')
    # trader.start()

    # strategy
    print('start execute strategy')
    today = datetime.date.today()
    yesterday = datetime.date.today() + datetime.timedelta(days=-1)
    dd = SendOrder(code=codes, frequence='5min', strategy_id=acc.message['account_cookie'], start=yesterday, end=today)
    dd.run_sim()



if __name__ == "__main__":
    # try:
    #     from QUANTAXIS_RealtimeCollector.QARealtimeCollector.utils.logconf import update_log_file_config
    #     logfile = 'stock.sim.log'
    #     logging.config.dictConfig(update_log_file_config(logfile))
    # except Exception as e:
    #     print(e.__str__())
    main()
